<template>
    <div class="common-layout">
        <el-container>
            <el-aside>
                <el-card shadow="never">
                    <el-input v-model="deptName" placeholder="部门名称" clearable>
                        <template #prefix>
                            <i-ep-search />
                        </template>
                    </el-input>

                    <el-tree ref="deptTreeRef" class="mt-2" :data="deptList"
                        :props="{ children: 'children', label: 'label', disabled: '' }" :expand-on-click-node="false"
                        :filter-node-method="handleFilter" default-expand-all @node-click="handleNodeClick" />
                </el-card>
            </el-aside>
            <el-container>
                <el-header>
                    <div class="search-container">
                        <el-form ref="queryFormRef" :model="queryParams" :inline="true">
                            <el-form-item label="关键字" prop="keywords">
                                <el-input v-model="queryParams.keywords" placeholder="用户名/昵称/手机号" clearable
                                    style="width: 200px" @keyup.enter="handleQuery" />
                            </el-form-item>

                            <el-form-item label="状态" prop="status">
                                <el-select v-model="queryParams.status" placeholder="全部" clearable class="!w-[100px]">
                                    <el-option label="启用" value="1" />
                                    <el-option label="禁用" value="0" />
                                </el-select>
                            </el-form-item>

                            <el-form-item label="创建时间">
                                <el-date-picker class="!w-[240px]" v-model="dateTimeRange" type="daterange"
                                    range-separator="~" start-placeholder="开始时间" end-placeholder="截止时间"
                                    value-format="YYYY-MM-DD" />
                            </el-form-item>

                            <el-form-item>
                                <el-button type="primary" @click="handleQuery"><i-ep-search />搜索</el-button>
                                <el-button @click="handleResetQuery">
                                    <i-ep-refresh />
                                    重置</el-button>
                            </el-form-item>
                        </el-form>
                    </div>
                </el-header>
                <el-main>
                    <div>
                        <div class="flex justify-between">
                            <div>
                                <el-button type="success" @click="openDialog('user-form')"><i-ep-plus />新增</el-button>
                                <el-button type="danger" :disabled="removeIds.length === 0"
                                    @click="handleDelete()"><i-ep-delete />删除</el-button>
                            </div>
                            <div>
                                <el-dropdown split-button>
                                    导入
                                    <template #dropdown>
                                        <el-dropdown-menu>
                                            <el-dropdown-item @click="downloadTemplate">
                                                <i-ep-download />下载模板</el-dropdown-item>
                                            <el-dropdown-item @click="openDialog('user-import')">
                                                <i-ep-top />导入数据</el-dropdown-item>
                                        </el-dropdown-menu>
                                    </template>
                                </el-dropdown>
                                <el-button class="ml-3" @click="handleExport"><template
                                        #icon><i-ep-download /></template>导出</el-button>
                            </div>
                        </div>
                    </div>
                    <el-table :data="pageData" style="width: 100%" @selection-change="handleSelectionChange">
                        <el-table-column type="selection" width="50" align="center" />
                        <el-table-column key="id" prop="id" label="编号" align="center" width="100" />
                        <el-table-column key="username" prop="username" label="用户名" align="center" />
                        <el-table-column prop="nickname" label="用户昵称" align="center" width="120" />
                        <el-table-column prop="genderLabel" label="性别" width="100" align="center" />
                        <el-table-column prop="deptName" label="部门" width="120" align="center" />
                        <el-table-column prop="mobile" label="手机号码" width="120" align="center" />
                        <el-table-column prop="status" label="状态" align="center">
                            <template #default="scope">
                                <el-tag :type="scope.row.status == 1 ? 'success' : 'info'">{{ scope.row.status == 1 ?
                                    "启用" : "禁用"
                                    }}</el-tag>
                            </template>
                        </el-table-column>
                        <el-table-column prop="createTime" label="创建时间" width="180" align="center" />
                        <el-table-column fixed="right" label="操作" width="220" align="center">
                            <template #default="scope">
                                <el-button type="primary" size="small" link @click="resetPassword(scope.row)">
                                    <i-ep-refresh-left />重置密码
                                </el-button>
                                <el-button type="primary" size="small" link
                                    @click="openDialog('user-form', scope.row.id)">
                                    <i-ep-edit />编辑
                                </el-button>
                                <el-button type="primary" size="small" link @click="handleDelete(scope.row.id)">
                                    <i-ep-delete />删除
                                </el-button>
                            </template>
                        </el-table-column>
                    </el-table>
                    <!-- 分页 -->
                    <el-pagination v-model:current-page="queryParams.pageNum" v-model:page-size="queryParams.pageSize"
                        :page-sizes="[1, 3, 5, 10]" :small="false" :disabled="false" :background="true"
                        layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange"
                        @current-change="handleCurrentChange" />
                    <!-- 弹窗 -->
                    <el-dialog v-model="dialog.visible" :title="dialog.title" :width="dialog.width" append-to-body
                        @close="closeDialog">
                        <!-- 用户新增或编辑菜单 -->
                        <el-form v-if="dialog.type === 'user-form'" ref="userFormRef" :model="formData" :rules="rules"
                            label-width="80px">
                            <el-form-item label="用户名" prop="username">
                                <el-input v-model="formData.username" placeholder="请输入用户名" :readonly="!!formData.id" />
                            </el-form-item>
                            <el-form-item label="用户昵称" prop="nickname">
                                <el-input v-model="formData.nickname" placeholder="请输入用户昵称" />
                            </el-form-item>
                            <el-form-item label="所属部门" prop="deptId">
                                <el-tree-select v-model="formData.deptId" placeholder="请选择所属部门" :data="deptList"
                                    filterable check-strictly :render-after-expand="false" />
                            </el-form-item>
                            <el-form-item label="性别" prop="gender">
                                <dictionary v-model="formData.gender" type-code="gender" />
                            </el-form-item>
                            <el-form-item label="角色" prop="roleIds">
                                <el-select v-model="formData.roleIds" multiple placeholder="请选择">
                                    <el-option v-for="item in roleList" :key="item.value" :label="item.label"
                                        :value="item.value" />
                                </el-select>
                            </el-form-item>
                            <el-form-item label="手机号码" prop="mobile">
                                <el-input v-model="formData.mobile" placeholder="请输入手机号码" maxlength="11" />
                            </el-form-item>
                            <el-form-item label="邮箱" prop="email">
                                <el-input v-model="formData.email" placeholder="请输入邮箱" maxlength="50" />
                            </el-form-item>
                            <el-form-item label="状态" prop="status">
                                <el-radio-group v-model="formData.status">
                                    <el-radio :label="1">正常</el-radio>
                                    <el-radio :label="0">禁用</el-radio>
                                </el-radio-group>
                            </el-form-item>
                        </el-form>
                        <!-- 用户导入表单 -->
                        <el-form v-else-if="dialog.type === 'user-import'" :model="importData" label-width="100px">
                            <el-form-item label="部门">
                                <el-tree-select v-model="importData.deptId" placeholder="请选择部门" :data="deptList"
                                    filterable check-strictly />
                            </el-form-item>
                            <el-form-item label="Excel文件">
                                <el-upload ref="uploadRef" action="" drag
                                    accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
                                    :limit="1" :auto-upload="false" :file-list="importData.fileList"
                                    :on-change="handleFileChange" :on-exceed="handleFileExceed">
                                    <el-icon class="el-icon--upload">
                                        <i-ep-upload-filled />
                                    </el-icon>
                                    <div class="el-upload__text">
                                        将文件拖到此处，或
                                        <em>点击上传</em>
                                    </div>
                                    <template #tip>
                                        <div>xls/xlsx files</div>
                                    </template>
                                </el-upload>
                            </el-form-item>
                        </el-form>
                        <template #footer>
                            <div class="dialog-footer">
                                <el-button type="primary" @click="handleSubmit"> 确 定 </el-button>
                                <el-button @click="closeDialog"> 取 消 </el-button>
                            </div>
                        </template>
                    </el-dialog>
                </el-main>
            </el-container>
        </el-container>
    </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
// 调用SVG
import SvgIcon from '@/components/SvgIcon/index.vue'

// 调用接口
import { imports, exports, downloadTemplate, deleteByIds, updatePassword, update, add, getFormData, getPage, getInfo } from '@/api/user/index';
import { getOptions } from '@/api/dept'
import { getOptionss } from '@/api/role'
// 调用类型
import type { UserInfo, UserQuery, UserPageV0, UserForm } from '@/api/user/model'
import type { UploadInstance } from "element-plus";
import { genFileId } from "element-plus";
import type { OptionType } from 'element-plus/es/components/select-v2/src/select.types.mjs';
import { useThrottleFn, useVModel } from '@vueuse/core';

// 部门树
const props = defineProps({
    modelValue: {
        type: [Number],
        default: undefined,
    },
});
// 表单
defineOptions({
    name: "User",
    inheritAttrs: false,
});
// 分页
const handleSizeChange = (val: number) => {
    queryParams.pageSize = val
    //   console.log(`${val} items per page`)
    handleQuery()
}
const handleCurrentChange = (val: number) => {
    queryParams.pageNum = val
    //   console.log(`current page: ${val}`)
    handleQuery()
}

const deptList = ref<OptionType[]>(); // 部门列表
const deptTreeRef = ref(ElTree); // 部门树
const deptName = ref(); // 部门名称
const queryFormRef = ref(ElForm); // 查询表单
const userFormRef = ref(ElForm); // 用户表单
const uploadRef = ref<UploadInstance>(); // 上传组件

const loading = ref(false); //  加载状态
const removeIds = ref([]); // 删除用户ID集合 用于批量删除
const queryParams = reactive<UserQuery>({
    pageNum: 1,
    pageSize: 10,
});
const dateTimeRange = ref("");
const total = ref(0); // 数据总数
const pageData = ref<UserPageV0[]>(); // 用户分页数据
const roleList = ref<OptionType[]>(); // 角色下拉数据源

const emits = defineEmits(["node-click"]);

const deptId = useVModel(props, "modelValue", emits);

watchEffect(
    () => {
        deptTreeRef.value.filter(deptName.value);
    },
    {
        flush: "post", // watchEffect会在DOM挂载或者更新之前就会触发，此属性控制在DOM元素更新后运行
    }
);
/** 部门筛选 */
function handleFilter(value: string, data: any) {
    if (!value) {
        return true;
    }
    return data.label.indexOf(value) !== -1;
}

/** 部门树节点 Click */
function handleNodeClick(data: { [key: string]: any }) {
    deptId.value = data.value;
    emits("node-click");
}

onBeforeMount(async () => {
    await getOptions().then((data) => {
        deptList.value = data;
    });
});


// `````````````````````
watch(dateTimeRange, (newVal) => {
    if (newVal) {
        queryParams.startTime = newVal[0];
        queryParams.endTime = newVal[1];
    }
});
// 弹窗对象
const dialog = reactive({
    visible: false,
    type: "user-form",
    width: 800,
    title: "",
});

// 用户表单数据
const formData = reactive<UserForm>({
    status: 1,
});

// 用户导入数据
const importData = reactive({
    deptId: undefined,
    file: undefined,
    fileList: [],
});

// 校验规则
const rules = reactive({
    username: [{ required: true, message: "用户名不能为空", trigger: "blur" }],
    nickname: [{ required: true, message: "用户昵称不能为空", trigger: "blur" }],
    deptId: [{ required: true, message: "所属部门不能为空", trigger: "blur" }],
    roleIds: [{ required: true, message: "用户角色不能为空", trigger: "blur" }],
    email: [
        {
            pattern: /\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/,
            message: "请输入正确的邮箱地址",
            trigger: "blur",
        },
    ],
    mobile: [
        {
            pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
            message: "请输入正确的手机号码",
            trigger: "blur",
        },
    ],
});

/** 查询 */
async function handleQuery() {
    loading.value = true;
    await getPage(queryParams)
        .then((data) => {
            console.log("handleQuery", data);
            pageData.value = data.list;
            total.value = data.total;
        })
        .finally(() => {
            loading.value = false;
        });
}

/** 重置查询 */
function handleResetQuery() {
    queryFormRef.value.resetFields();
    dateTimeRange.value = "";
    queryParams.pageNum = 1;
    queryParams.deptId = undefined;
    queryParams.startTime = undefined;
    queryParams.endTime = undefined;
    handleQuery();
}

/** 行选中 */
function handleSelectionChange(selection: any) {
    removeIds.value = selection.map((item: any) => item.id);
}

/** 重置密码 */
function resetPassword(row: { [key: string]: any }) {
    ElMessageBox.prompt(
        "请输入用户「" + row.username + "」的新密码",
        "重置密码",
        {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
        }
    ).then(({ value }) => {
        if (!value || value.length < 6) {
            // 检查密码是否为空或少于6位
            ElMessage.warning("密码至少需要6位字符，请重新输入");
            return false;
        }
        updatePassword(row.id, value).then(() => {
            ElMessage.success("密码重置成功，新密码是：" + value);
        });
    });
}

/** 加载角色下拉数据源 */
async function loadRoleOptions() {
    await getOptionss().then((data) => {
        roleList.value = data;
    });
}

/** 加载部门下拉数据源 */
async function loadDeptOptions() {
    await getOptions().then((data) => {
        deptList.value = data;
    });
}

/**
 * 打开弹窗
 *
 * @param type 弹窗类型  用户表单：user-form | 用户导入：user-import
 * @param id 用户ID
 */
async function openDialog(type: string, id?: number) {
    dialog.visible = true;
    dialog.type = type;

    if (dialog.type === "user-form") {
        // 用户表单弹窗
        await loadDeptOptions();
        await loadRoleOptions();
        if (id) {
            dialog.title = "修改用户";
            getFormData(id).then((data) => {
                Object.assign(formData, { ...data });
            });
        } else {
            dialog.title = "新增用户";
        }
    } else if (dialog.type === "user-import") {
        // 用户导入弹窗
        dialog.title = "导入用户";
        dialog.width = 600;
        loadDeptOptions();
    }
}

/**
 * 关闭弹窗
 *
 * @param type 弹窗类型  用户表单：user-form | 用户导入：user-import
 */
function closeDialog() {
    dialog.visible = false;
    if (dialog.type === "user-form") {
        userFormRef.value.resetFields();
        userFormRef.value.clearValidate();

        formData.id = undefined;
        formData.status = 1;
    } else if (dialog.type === "user-import") {
        importData.file = undefined;
        importData.fileList = [];
    }
}

/** 表单提交 */
const handleSubmit = useThrottleFn(() => {
    if (dialog.type === "user-form") {
        userFormRef.value.validate((valid: any) => {
            if (valid) {
                const userId = formData.id;
                loading.value = true;
                if (userId) {
                    update(userId, formData)
                        .then(() => {
                            ElMessage.success("修改用户成功");
                            closeDialog();
                            handleResetQuery();
                        })
                        .finally(() => (loading.value = false));
                } else {
                    add(formData)
                        .then(() => {
                            ElMessage.success("新增用户成功");
                            closeDialog();
                            handleResetQuery();
                        })
                        .finally(() => (loading.value = false));
                }
            }
        });
    } else if (dialog.type === "user-import") {
        if (!importData?.deptId) {
            ElMessage.warning("请选择部门");
            return false;
        }
        if (!importData?.file) {
            ElMessage.warning("上传Excel文件不能为空");
            return false;
        }
        imports(importData?.deptId, importData?.file).then((data) => {
            ElMessage.success("导入用户成功");
            closeDialog();
            handleResetQuery();
        });
    }
}, 3000);

/** 删除用户 */
function handleDelete(id?: number) {
    const userIds = [id || removeIds.value].join(",");
    if (!userIds) {
        ElMessage.warning("请勾选删除项");
        return;
    }

    ElMessageBox.confirm("确认删除用户?", "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
    }).then(function () {
        deleteByIds(userIds).then(() => {
            ElMessage.success("删除成功");
            handleResetQuery();
        });
    });
}

/** 下载导入模板 */
async function downloadTemplate() {
    await downloadTemplate().then((response: any) => {
        const fileData = response.data;
        const fileName = decodeURI(
            response.headers["content-disposition"].split(";")[1].split("=")[1]
        );
        const fileType =
            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8";

        const blob = new Blob([fileData], { type: fileType });
        const downloadUrl = window.URL.createObjectURL(blob);

        const downloadLink = document.createElement("a");
        downloadLink.href = downloadUrl;
        downloadLink.download = fileName;

        document.body.appendChild(downloadLink);
        downloadLink.click();

        document.body.removeChild(downloadLink);
        window.URL.revokeObjectURL(downloadUrl);
    });
}

/** Excel文件 Change */
function handleFileChange(file: any) {
    importData.file = file.raw;
}

/** Excel文件 Exceed  */
function handleFileExceed(files: any) {
    uploadRef.value!.clearFiles();
    const file = files[0];
    file.uid = genFileId();
    uploadRef.value!.handleStart(file);
    importData.file = file;
}

/** 导出用户 */
async function handleExport() {
    await exports(queryParams).then((response: any) => {
        const fileData = response.data;
        const fileName = decodeURI(
            response.headers["content-disposition"].split(";")[1].split("=")[1]
        );
        const fileType =
            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8";

        const blob = new Blob([fileData], { type: fileType });
        const downloadUrl = window.URL.createObjectURL(blob);

        const downloadLink = document.createElement("a");
        downloadLink.href = downloadUrl;
        downloadLink.download = fileName;

        document.body.appendChild(downloadLink);
        downloadLink.click();

        document.body.removeChild(downloadLink);
        window.URL.revokeObjectURL(downloadUrl);
    });
}

onMounted(() => {
    handleQuery();
});
</script>

<style scoped>
.el-aside {
    background-color: white;
    width: 220px;
    padding-bottom: 30px;
    padding: 0 10px;
    box-sizing: border-box;
}

.left {
    position: relative;
    text-align: center;
    padding-top: 20px;
    box-sizing: border-box;
}

.left_bom {
    margin-top: 10px;
}

::v-deep.el-input input {
    padding-left: 20px;
    box-sizing: border-box;
}

.svgs {
    position: absolute;
    z-index: 1;
    top: 28px;
    left: 10px;
}



.el-header,
.el-main {
    margin-left: 20px;
    background-color: white;
}

.el-main {
    margin-top: 10px;
}

.el-header {
    height: 50px;
    padding: 10px 20px;
    box-sizing: border-box;
}

.el-pagination {
    margin-top: 20px;
}
</style>